Win32Dib is a Euphoria-library that provides fast bitmap manipulation (24-bit graphics) to Win32Lib-applications.
Win32Dib is derived from my Shibby-library. I will no longer continue development of Shibby, so if you were using Shibby, I suggest you stop using it and start using Win32Dib, which is a lot faster and uses memory more efficiently. The names of constants, procedures and functions have changed to follow the naming convention used by Win32Lib. This makes sure that the code of your programs will look more consistent. Shibby used 32-bit graphics, which is silly because only 24 bits are really used. So Win32Dib now uses 24-bit graphics.
To use Win32Dib, you need Win32Lib 0.60 or a more recent version, but I don't think this is a problem, right?
Thanks go to:
Content: Reading version info, creating and deleting bitmaps, pixels and colors, loading and save bitmaps, copying bitmaps, bitmap manipulation, optimization.
Win32Dib has a constant that contains information about the version: Win32DibVersion
,
which is a sequence of length 4:
Win32DibVersion[1]
is the Major version (integer).
Win32DibVersion[2]
is the Minor version (integer).
Win32DibVersion[3]
is the Patch/Revision (integer).
Win32DibVersion[4]
is the release date (string sequence).
A Win32Dib-bitmap is a sequence of length 7:
dib[DibHandle]
is the bitmap handle (integer) you can use in Win32Lib-routines.
dib[DibMemory]
is the address (atom) of the memory block of the bitmap.
dib[DibWidth]
is the width of the bitmap in pixels.
dib[DibHeight]
is the height of the bitmap in pixels.
dib[DibBytesPerLine]
is the amount of bytes per line of the bitmap.
dib[DibBytesTotal]
is the total amount of bytes of the bitmap.
dib[DibPadding]
is the amount of bytes of padding after each scanline.
To create a new bitmap, you use the newDib-function. After you don't need the bitmap anymore, you have to delete it by calling the killDib-procedure. You can also create a copy of an existing bitmap by calling the copyDib-function.
Example:
sequence dib, dib2 dib = newDib(width, height) -- create a new bitmap with the specified width and height if integer(dib) then -- the bitmap couldn't be created end if dib2 = copyDib(dib) -- creates a copy of the first bitmap ... -- some code killDib(dib) killDib(dib2) -- delete the bitmaps. YOU HAVE TO DO THIS.
One thing you should really know is that colors in Win32Dib-bitmaps are not stored as RGB, but as BGR. What does this mean? Every pixel is 3 bytes. Each byte represents the intensity of a primary color component: 1 byte red, 1 byte green and 1 byte blue. 0 means no intensity, 255 means full intensity. BGR means that for each pixel, the color is stored as {blue, green, red} instead of {red, green, blue}. To create a color, just create a sequence {blue, green, red}. If you're used to working with RGB-colors and you miss a lot, you can use the dibColor-function, which returns the right sequence.
Example:
sequence color color = dibColor(255, 0, 0) -- full red, no green, no blue => bright red color = dibColor(255, 255, 0) -- full red, full green, no blue => bright yellow color = dibColor( 0, 0, 0) -- no red, no green, no blue => black color = dibColor(255, 255, 255) -- full red, full green, full blue => bright white color = dibColor( 0, 127, 255) -- no red, half green, full blue => some kind of cyanTo put a pixel on the bitmap, use the putDibPixel-procedure. To get the color of a pixel on the bitmap, use the getDibPixel-function. To clear the bitmap, use the clearDib-procedure. Instead of putDibPixel and getDibPixel, you can also use the faster fastPutDibPixel and fastGetDibPixel, but these don't check if the coordinates of the pixel are within the boundaries of the bitmap, so only use them if you're sure the coordinates are valid (0 <= x < width and 0 <= y < height).
Example:
sequence dib, white, black, color dib = newDib(300, 200) -- create a bitmap white = dibColor(255, 255, 255) -- create the color white black = dibColor( 0, 0, 0) -- create the color black clearDib(dib, white) -- clear the bitmap with the color white putDibPixel(dib, 100, 100, black) -- make the pixel at position (100, 100) black color = getDibPixel(dib, 200, 150) -- get the color of the pixel at position (200, 150) killDib(dib) -- delete the bitmap
If you have to put or get a lot of pixels, there is a much faster way than using putDibPixel and getDibPixel: poke and peek. The 2nd element of the bitmap-sequence is the address of the memory block allocated by the bitmap. To calculate the address of the pixel (x, y), use the formula:
integer bytes_per_line atom memory, address memory = dib[DibMemory] bytes_per_line = dib[DibBytesPerLine] address = memory + 3 * x + y * bytes_per_lineTo get the color of the pixel:
sequence color color = peek({address, 3}) -- each pixel is 3 bytesTo set the color of the pixel:
poke(address, color)A very fast way to loop over the entire bitmap goes like this:
atom address address = dib[DibMemory] for y = 0 to height - 1 do for x = 0 to width - 1 do -- do something with the current pixel: -- address is the address, x and y are the coordinates. address += 3 -- 1 pixel = 3 bytes end for address += padding -- padding is the integer dib[DibPadding] end forIf you only want to loop over a region (x1, y1) -> (x2, y2), you can try:
atom address integer line_jump address = dib[DibMemory] + x1 * 3 + y1 * bytes_per_line line_jump = bytes_per_line + (x1 - x2) * 3 + 3 for y = y1 to y2 do for x = x1 to x2 do -- do something with the current pixel: -- address is the address, x and y are the coordinates. address += 3 end for address += line_jump -- line_jump is the amount of bytes to jump forward after each line end for
You can load a bitmap from a BMP-file with the loadDib-function. You can save (a region of) the bitmap to a 24-bit BMP-file with the saveDib-function. This function returns 0 if successful, or 1 if the bitmap couldn't be saved. You can also save (a region of) the bitmap as an 8-bit grayscale BMP-file with the saveDibGray-function (same parameters and return value like saveDib), or as an 8-bit websafe color BMP-file with the saveDibReduced-function.
integer result object dib dib = loadDib("bitmap1.bmp") -- loads the bitmap if integer(dib) then -- couldn't load the bitmap abort(0) end if result = saveDib(dib, "bitmap2.bmp", 10, 10, 100, 75) -- saves the rectangular region (10, 10) -> (100, 75) -- to the file "bitmap2.bmp". if result then ... -- the bitmap couldn't be saved end if
The drawDib-procedure draws (a region of) the bitmap to a Win32Lib control or window:
drawDib(control, dib, x, y, x1, y1, x2, y2) -- draws the rectangular region (x1, y1) -> (x2, y2) from the dib on the control at -- position (x, y).
The copyToDib-procedure draws (a region of) a Win32Lib control or window to the bitmap:
copyToDib(dib, control, x, y, x1, y1, x2, y2) -- draws the rectangular region (x1, y1) -> (x2, y2) from the control on the dib at -- position (x, y)
The drawDibToDib-procedure draws (a region of) a bitmap to a different bitmap:
drawDibToDib(dest, src, x, y, x1, y1, x2, y2, trans_color, alpha) -- draws the rectangular region (x1, y1) -> (x2, y2) from bitmap src on the bitmap dest -- at position (x, y) with a translucency of alpha (0 = transparent, 255 = opaque). -- The pixels from src that have a color equal to trans_color are not drawn. -- If trans_color is an empty sequence, no transparency is used.
(The drawTransDibToDib-procedure doesn't exist anymore: the transparency-functionality has been implemented in drawDibToDib).
The applyDibBrightnessToDib-procedure applies the brightness of (a region of) a bitmap to a different bitmap:
applyDibBrightnessToDib(dest, src, x, y, x1, y1, x2, y2, pct) -- applies the brightness of the rectangular region (x1, y1) -> (x2, y2) from bitmap src -- on the bitmap dest at position (x, y). pct is a percentage (0-100): 0 = don't apply -- any brightness, 100 = apply full brightness, 50 = apply half the brightness, ...
The tileDibToDib-procedure fills a bitmap with another bitmap as pattern (tile):
tileDibToDib(dest, src, x, y, x1, y1, x2, y2, trans_color, alpha) -- fills the bitmap dest with the rectangular region (x1, y1) -> (x2, y2) from bitmap -- src as a pattern, using point (x, y) as a starting point. See drawDibToDib for -- trans_color and alpha.
The drawDibTransformedPolygon-procedure draws a polygonal region from a bitmap onto a different polygonal region from a different bitmap.
drawDibTransformedPolygon(dest, src, pol_dest, pol_src) -- draws the region inside polygon pol_src from bitmap src onto the region inside -- polygon pol_dest from bitmap dest. pol_src and pol_dest are sequences that look like -- {{x1, y1}, {x2, y2}, ...}. If you pass an empty sequence, the bounding rectangle of -- the bitmap will be used. Both polygons must be convex.
The copyDibToDib-procedure copies a bitmap to another bitmap. Both bitmaps need to have the same size:
copyDibToDib(dib_dest, dib_source) -- copies the bitmap dib_source to the bitmap dib_dest
The extractDib-function extracts a bitmap from another bitmap or control, and returns it:
sequence dib dib = extractDib(src, x1, y1, x2, y2) -- extracts the rectangular region (x1, y1) -> (x2, y2) from bitmap or control src and -- returns it as a bitmap
The copyDibToClipboard-procedure copies a bitmap to the clipboard:
copyDibToClipboard(dib) -- copies the bitmap dib to the clipboard
The getDibFromClipboard-function gets a bitmap from the clipboard and returns it:
object dib dib = getDibFromClipboard() -- copies a bitmap from the clipboard and puts it in dib -- dib will be 0 if a bitmap couldn't be copied from the clipboard
Example: you can use a bitmap to save a screenshot to a bitmap:
sequence dib integer result dib = newDib(screen_width, screen_height) -- create the bitmap copyToDib(dib, Screen, 0, 0, 0, 0, screen_width - 1, screen_height - 1) -- copy the screen to the bitmap result = saveDib(dib, "screen.bmp", 0, 0, screen_width - 1, screen_height - 1) -- save the bitmap to a file killDib(dib) -- delete the bitmap
The following routines can be used to manipulate a bitmap:
for each pixel[y, x] in the bitmap do pixel[y, x] = sum(pixel[y-4+i, x-4+j]; i = 1 to 7, j = 1 to 7) / div + bias end for